home *** CD-ROM | disk | FTP | other *** search
- #include "qix.h"
- #include "math.h"
-
- /* the pen marker */
- short marker_curs_dat[] = {
- #include "marker.cursor"
- };
- mpr_static(pen_image, 16, 16, 1, marker_curs_dat);
-
- short fast_draw_off_dat[] = {
- #include <images/mouse_left_hand.pr>
- };
- mpr_static(ms_fast_off, 16, 23, 1, fast_draw_off_dat);
-
- short fast_draw_on_dat[] = {
- #include <images/mouse_left_hand_grey.pr>
- };
- mpr_static(ms_fast_on, 16, 23, 1, fast_draw_on_dat);
-
- short slow_draw_off_dat[] = {
- #include <images/mouse_mid_hand.pr>
- };
- mpr_static(ms_slow_off, 16, 23, 1, slow_draw_off_dat);
-
- short slow_draw_on_dat[] = {
- #include <images/mouse_mid_hand_grey.pr>
- };
- mpr_static(ms_slow_on, 16, 23, 1, slow_draw_on_dat);
-
- /* joystick (really, arrow) symbols */
- short left_arrow_dat[] = {
- #include "joystick.lf"
- };
- mpr_static(joystick_left, 64, 64, 1, left_arrow_dat);
-
- short right_arrow_dat[] = {
- #include "joystick.rt"
- };
- mpr_static(joystick_right, 64, 64, 1, right_arrow_dat);
-
- short up_arrow_dat[] = {
- #include "joystick.up"
- };
- mpr_static(joystick_up, 64, 64, 1, up_arrow_dat);
-
- short dn_arrow_dat[] = {
- #include "joystick.dn"
- };
- mpr_static(joystick_down, 64, 64, 1, dn_arrow_dat);
-
- /* a circle with line thru it */
- short stop_dat[] = {
- #include "joystick.stop"
- };
- mpr_static(joystick_stop, 64, 64, 1, stop_dat);
-
- /* a big right mouse button */
- short ready_icon_dat[] = {
- #include "mouse.rt.icon"
- };
- mpr_static(ready_icon, 64, 64, 1, ready_icon_dat);
-
- /*
- * the main window selection catches input interrupts and calls this
- * routine to process what just happened. Nothing is actually done
- * besides that -- that is, the pen is not moved, the qix isn't moved,
- * and sparks don't move. however, we will reset the "moving" variable,
- * start the or finish the "drawing" state, and reset the icon that displays
- * the joystick icon that indicates which way the user is moving.
- */
- move_joystick(canvas, event, data)
- register Canvas canvas;
- register Event *event;
- {
- register int ID = event->ie_code;
- static start_fast;
-
- if (play_mode != REAL_PLAY && ID != ' ' && ID != MS_RIGHT)
- return;
-
- if ((ID == LOC_MOVE) && moving != NO_MOVE) {
- register int delta_x, delta_y;
- if (event_x(event) <= 0)
- event_set_x(event, 1);
- if (event_y(event) <= 0)
- event_set_y(event, 1);
- delta_x = event_x(event) - MID_X;
- delta_y = event_y(event) - MID_Y;
-
- /* didn't move enough */
- if (abs(delta_x) <= SENS_FACTOR && abs(delta_y) <= SENS_FACTOR)
- return;
-
- if (abs(delta_x) > abs(delta_y))
- if (delta_x > 0)
- moving = RIGHT;
- else
- moving = LEFT;
- else
- if (delta_y > 0)
- moving = DOWN;
- else
- moving = UP;
- }
-
- if (isascii(ID) && ID != ' ') {
- #ifdef DEBUG
- if (isdigit(ID)) {
- debug = ID - '0';
- msg("Debugging level set to %d", debug);
- sleep(2);
- remove_msgs();
- return;
- } else
- #endif DEBUG
- if (event_is_up(event)) {
- /* up events -- user released a key, so stop moving */
- /* unimplemented -- holding key down results in fast up/down's */
- moving = STOP;
- drawing = 0;
- return;
- } else if (event_shift_is_down(event))
- fast = drawing = 1;
- else if (event_meta_is_down(event))
- fast = !(drawing = 1);
- else
- drawing = 0;
- }
-
- switch(ID) {
- when MS_LEFT :
- fast = (drawing = (!event_is_up(event)));
- start_fast = TRUE;
- return;
- when MS_MIDDLE :
- fast = 0;
- if (start_fast == TRUE && region)
- drawing = 0;
- else
- drawing = !event_is_up(event);
- return;
- when MS_RIGHT : case ' ' :
- if (event_is_up(event))
- break;
- /* if moving == NO_MOVE, RIGHT, LEFT, UP or DOWN */
- if (!is_alive || play_mode != REAL_PLAY) {
- lives = 0;
- play_mode = REAL_PLAY; /* set Nowhere else but here! */
- change_life(LIVE); /* "next" life in current game */
- } else if (moving != STOP) {
- /* NO_MOVE state goes right to STOP state */
- if (moving == NO_MOVE)
- reset_joystick_win(FALSE);
- /* all other directions go right to STOP state */
- moving = STOP;
- } else
- /* STOP state goes right to NO_MOVE state */
- moving = NO_MOVE, reset_joystick_win(TRUE);
- when 'h' : case 'H' : case KEY_RIGHT(10) :
- moving = LEFT;
- when 'l' : case 'L' : case KEY_RIGHT(12) :
- moving = RIGHT;
- when 'j' : case 'J' : case KEY_RIGHT(14) :
- moving = DOWN;
- when 'k' : case 'K' : case KEY_RIGHT(8) :
- moving = UP;
- when LOC_MOVE : break; /* let those thru! */
- #ifdef DEBUG
- case '@' : no_qix_kill = !no_qix_kill; drawing = 0;
- when '#' : clear_sparks();
- when '+' : lives = min(lives+1, MAX_LIVES); update_score(); drawing = 0;
- when '-' : lives = max(lives-1, 1); update_score(); drawing = 0;
- when '!' : drawing = 0;
- if (play_mode == REAL_PLAY) {
- lives = 0;
- change_life(LIVE);
- } /* fall thru */
- #endif DEBUG
- default :
- return; /* do nothing */
- }
- if (moving != NO_MOVE &&
- (event_x(event) != MID_X || event_y(event) != MID_Y))
- window_set(canvas, WIN_MOUSE_XY, MID_X, MID_Y, 0);
- }
-
- /*
- * The main routine waits for input from the user until an alarm goes off
- * which says, "ok, go to the next state of the machine" which may very
- * well be "do nothing". The timer is restarted when we're done processing
- * whatever we have to process. This is where the pen actually moves to the
- * next position, drawing lines, or running scared from a vicious spark.
- */
- move_pen()
- {
- register int x = pen_x, y = pen_y, new_value, old_value;
- static slow_draw;
-
- if (!is_alive && lives > 0) {
- /* user has died and is waiting to start again */
- sleep(2);
- change_life(LIVE);
- stop_timer(); /* change_life restarts it */
- msg("Ready?");
- sleep(2);
- remove_msgs(0);
- start_timer();
- return;
- }
- /* don't play if the joystick isn't active */
- if (moving == NO_MOVE || play_mode != REAL_PLAY) {
- if (play_mode != REAL_PLAY) {
- time_left--;
- if (play_mode == DEMO && lives > 0) {
- if (time_left == 0) {
- int lastmove = moving;
- register int left, right, up, down;
- drawing = 1;
- if (!(board[x][y] & NEW_LINE))
- fast = (rrand() & 3);
- left = (!check_painted(x, y, CL_PNT_LEFT) &&
- !(board[x-1][y] & NEW_LINE));
-
- right = (!check_painted(x, y, CL_PNT_RIGHT) &&
- !(board[x+1][y] & NEW_LINE));
-
- up = (!check_painted(x, y, CL_PNT_TOP) &&
- !(board[x][y-1] & NEW_LINE));
-
- down = (!check_painted(x, y, CL_PNT_BOT) &&
- !(board[x][y+1] & NEW_LINE));
-
- if (!left && !right && !up && !down)
- moving = STOP, time_left = -1; /* let fuse catch up */
- else {
- int dx = region ? region->x - x : 0;
- int dy = region ? region->y - y : 0;
- time_left = 15 + (rrand() & 31);
- /* first attempt to limit box to less than 25 X 25 */
- if (region && (_ABS(dx) > 25 || _ABS(dy) > 25)) {
- if (_ABS(dx) > 25 ||
- _ABS(dy) > 25 && (moving == LEFT ||
- moving == RIGHT))
- if (moving != LEFT && moving != RIGHT)
- moving = (dx > 25) ? RIGHT : LEFT;
- else
- moving = (dy > 0) ? DOWN : UP;
- else if (_ABS(dy) > 25)
- if (moving != UP && moving != DOWN)
- moving = (dy > 25) ? DOWN : UP;
- else
- moving = (dx > 0) ? RIGHT : LEFT;
- }
- /* Make sure we can move in that direction */
- while (moving == lastmove ||
- !left && moving == LEFT || !up && moving == UP ||
- !down && moving == DOWN || !right && moving== RIGHT)
- moving = LEFT + (rrand() & 3);
- }
- }
- } else if (time_left <= 0) {
- drawing = 0;
- level = -2;
- moving = NO_MOVE;
- init_qix();
- switch (play_mode = (play_mode + 1) % (DEMO+1)) {
- when SHOW_SCORES :
- clear_board();
- score_board(TRUE, FALSE);
- time_left = 50;
- when SHOW_POINTS :
- score = 0;
- update_score();
- move_fuse(fuse = NULL); /* just in case */
- rm_cur_line(PIX_CLR);
- clear_board();
- place_pen();
- msg("Direct the mouse to control joystick.");
- time_left = 315;
- moving = LEFT;
- when SHOW_QIX :
- remove_msgs(0);
- msg("Your Enemies:");
- sleep(2);
- time_left = 40;
- when SHOW_SPARKS :
- time_left = 90;
- when SHOW_FUSE :
- drawing = fast = 1;
- moving = UP;
- time_left = 280;
- when SHOW_SPIRAL :
- moving = STOP;
- drawing = 0;
- time_left = 100;
- when DEMO :
- time_left = 1;
- change_life(LIVE);
- stop_timer();
- msg("Enclose more than\n75%%\nof the play area for extra bonus.");
- sleep(2);
- remove_msgs(0);
- level = -2;
- drawing = fast = 1;
- goto done;
- }
- } else switch (play_mode) {
- when SHOW_QIX :
- move_qix();
- if (time_left == 1) {
- pw_text(draw_win, 200,200,PIX_SRC,big_font, "The qix.");
- sleep(2);
- }
- when SHOW_SPARKS :
- move_sparks();
- if (time_left == 1) {
- pw_text(draw_win, 15, 110, PIX_SRC, big_font, "Sparx.");
- pw_text(draw_win,625, 110, PIX_SRC, big_font, "Sparx.");
- sleep(2);
- }
- when SHOW_FUSE :
- /* after the pw_text, this moves into spiral death trap */
- switch (time_left) {
- when 230 :
- drawing = 0;
- pw_text(draw_win,
- convert_x(pen_x - 7), convert_y(pen_y + 7),
- PIX_SRC, big_font, "The fuse.");
- when 80 :
- pw_text(draw_win, 265, 445,
- PIX_SRC, big_font, "The Spiral Death Trap.");
- case 200 : case 240 : case 40 : case 20 :
- moving = LEFT, drawing = 1;
- when 110 : case 55 : case 30 : moving = RIGHT;
- when 126 : case 65 : case 35 : moving = UP;
- when 95 : case 45 : case 25 : moving = DOWN;
- }
- goto movit;
- when SHOW_SPIRAL :
- if (fuse) { /* when we die, fuse will be NULL */
- time_left = 2;
- goto movit;
- } else if (region) {
- move_fuse(fuse = NULL);
- rm_cur_line(PIX_SRC);
- }
- when SHOW_POINTS : {
- char buf[5];
- switch (time_left) {
- when 270 :
- msg("Use LEFT mouse button for Fast Draw.");
- drawing = fast = 1, moving = UP;
- score = 0;
- when 170 :
- msg("Use MIDDLE mouse button for Slow Draw.");
- drawing = 1, fast = 0, moving = UP;
- score = 0;
- when 250 : case 130 : moving = RIGHT;
- when 230 : case 90 : moving = DOWN;
- when 210 : drawing = 0, moving = RIGHT;
- pw_text(draw_win,
- convert_x(pen_x - 12), convert_y(pen_y - 25),
- PIX_SRC, big_font, sprintf(buf, "%d", score));
- when 49 : /* make sure region is closed */
- msg("Use RIGHT mouse button to STOP movement.");
- pw_text(draw_win,
- convert_x(pen_x - 12), convert_y(pen_y - 25),
- PIX_SRC, big_font, sprintf(buf, "%d", score));
- when 15 : drawing = 0, moving = RIGHT;
- }
- goto movit; /* avoid moving qix and sparks */
- }
- }
- }
- if (play_mode != DEMO)
- goto done;
- }
-
- if (move_qix() == -1) {
- change_life(DIE);
- return;
- }
-
- if (move_sparks() == -1) /* player got hosed */
- return; /* don't restart timer */
-
- movit:
- draw_joystick();
- if (moving == STOP) {
- if (!cur_coord || move_fuse(&fuse) != -1) /* -1: fuse caught up */
- start_timer();
- return;
- }
- /* this forces the last fuse to go away */
- (void) move_fuse((struct region *)NULL); /* this can't return -1 */
- if (drawing && !fast && board[pen_x][pen_y] & NEW_LINE
- && (slow_draw = !slow_draw))
- goto done;
-
- /*
- * x,y will be the new (proposed) position if the following is true...
- * if not drawing, then check to see if the current cell we're at connects
- * with the proposed new position. Logic says that it will connect if
- * it "points" that way.. f'rinstance, you can't move left if the current
- * cell doesn't have the "cell-line-left" (CL_LN_LF) attribute. Also,
- * check to see if the current cell has the NEW_LINE attribute. If so,
- * user should be drawing. If he isn't, the fuse starts.
- */
- switch (moving) {
- when LEFT :
- if (check_painted(x, y, CL_PNT_LEFT) ||
- !drawing && !(board[x][y] & (CL_LN_LF|NEW_LINE))) {
- if (play_mode == DEMO)
- time_left = 1;
- goto done;
- }
- x--;
- when RIGHT :
- if (check_painted(x, y, CL_PNT_RIGHT) ||
- !drawing && !(board[x][y] & (CL_LN_RT|NEW_LINE))) {
- if (play_mode == DEMO)
- time_left = 1;
- goto done;
- }
- x++;
- when UP :
- if (check_painted(x, y, CL_PNT_TOP) ||
- !drawing && !(board[x][y] & (CL_LN_UP|NEW_LINE))) {
- if (play_mode == DEMO)
- time_left = 1;
- goto done;
- }
- --y;
- when DOWN :
- if (check_painted(x, y, CL_PNT_BOT) ||
- !drawing && !(board[x][y] & (CL_LN_DN|NEW_LINE))) {
- if (play_mode == DEMO)
- time_left = 1;
- goto done;
- }
- ++y;
- }
- old_value = board[pen_x][pen_y];
- new_value = board[x][y];
- /*
- * If drawing, you can't move onto yourself (a "new" line). [start fuse]
- * You can alwasy move onto an old line (completing a region if drawing).
- * If not drawing, you must be on an old line and moving
- * onto another old line. If we're not drawing and *should* be drawing
- * (determined by old_value's NEW_LINE bit set), start a fuse.
- * Also, player can't cheat by fast drawing and suddenly changing to
- * a slow draw just to close a region. Test to see if start_fast is
- * set correctly by testing "region" first.
- */
- if (drawing && (new_value & NEW_LINE) && !(new_value & OLD_LINE) ||
- !drawing && (old_value & NEW_LINE)) {
- if (!fuse) /* if a fuse isn't going, ignite one */
- fuse = region;
- if (play_mode == DEMO)
- time_left = 1;
- else
- moving = STOP;
- goto done;
- }
-
- /* erase the pen_image, move, reset pen_image, draw line */
- place_pen();
-
- /* next, determine that if we are drawing, ignore that fact if we
- * are attempting to draw on top of an already drawn line. If we
- * are creating a new line, then go ahead and create it.
- */
- if (drawing) {
- switch (moving) {
- when LEFT :
- if (board[pen_x][pen_y] & CL_LN_LF)
- goto redraw_pen;
- board[pen_x][pen_y] |= CL_LN_LF;
- board[x][y] |= CL_LN_RT;
- when RIGHT :
- if (board[pen_x][pen_y] & CL_LN_RT)
- goto redraw_pen;
- board[pen_x][pen_y] |= CL_LN_RT;
- board[x][y] |= CL_LN_LF;
- when UP :
- if (board[pen_x][pen_y] & CL_LN_UP)
- goto redraw_pen;
- board[pen_x][pen_y] |= CL_LN_UP;
- board[x][y] |= CL_LN_DN;
- when DOWN :
- if (board[pen_x][pen_y] & CL_LN_DN)
- goto redraw_pen;
- board[pen_x][pen_y] |= CL_LN_DN;
- board[x][y] |= CL_LN_UP;
- }
- draw(convert_x(x), convert_y(y),
- convert_x(pen_x), convert_y(pen_y), PIX_SRC);
- if (!region) {
- saved_edge = old_value;
- add_to_line(pen_x, pen_y);
- old_value = (board[pen_x][pen_y] |= NEW_LINE);
- }
- /* if drawing from a newline onto an old line, a region is completed */
- if ((old_value & NEW_LINE) && (new_value & OLD_LINE)) {
- int new_level = close_region(x, y);
- if (!new_level)
- update_score();
- if (new_level || (int)(((double)area_closed/TOTAL_AREA)*100) >= 75){
- if (!new_level) {
- int percent_closed =
- (int)(((double)area_closed/TOTAL_AREA) * 100);
- msg("Closed %d%% of the board.", percent_closed);
- if (percent_closed > 75) {
- score += (percent_closed - 75) * 1000;
- update_score();
- msg("1000 bonus points for each percent over 75%%");
- msg("BONUS: %d", (percent_closed - 75) * 1000);
- }
- } else
- level++;
- sleep(3);
- clear_board(); /* removes msgs also */
- change_life(LIVE);
- stop_timer();
- if (level < 0)
- level++;
- if (level == 0) {
- msg("Split the 2 qix to advance score multiplier.");
- sleep(2);
- remove_msgs(0);
- }
- start_timer();
- return;
- }
- } else if (new_value == 0) {
- board[x][y] |= NEW_LINE;
- add_to_line(x, y);
- }
- }
- redraw_pen:
- pen_x = x, pen_y = y;
- place_pen(); /* set the new pen image */
- done:
- start_timer();
- }
-
- draw_joystick()
- {
- Pixrect *image = moving == LEFT? &joystick_left :
- moving == RIGHT? &joystick_right :
- moving == UP? &joystick_up :
- moving == DOWN? &joystick_down :
- moving == STOP? &joystick_stop : &ready_icon;
- pw_rop(joystick_win,
- BOARD_WIDTH_IN_PIXELS/2-32, 2, 64, 64, PIX_SRC, image, 0,0);
- pw_rop(joystick_win, 100,32, 16,23, PIX_SRC,
- (drawing && fast)? &ms_fast_on : &ms_fast_off, 0, 0);
- pw_rop(joystick_win, 150,32, 16,23, PIX_SRC,
- (drawing && !fast)? &ms_slow_on : &ms_slow_off, 0, 0);
- }
-
- /*
- * if "see_it" -- then show the mouse cursor and stop moving mouse to middle
- * of window allowing allow player to grab beer. If "see_it" is
- * false, then the user is ready to move around, so make cursor go away,
- * and force all mouse moves to return to the middle of window.
- */
- reset_joystick_win(see_it)
- {
- static int oldop;
-
- Cursor cursor = (Cursor)window_get(Draw, WIN_CURSOR);
-
- if (!see_it) { /* we don't want to see the cursor, so get rid of it */
- /* get the current cursor and make it invisible */
- oldop = (int)cursor_get(cursor, CURSOR_OP);
- cursor_set(cursor, CURSOR_OP, PIX_DST, 0);
- moving = STOP;
- draw_joystick();
- } else {
- /* cursor_set(cursor, CURSOR_OP, oldop, 0); */
- moving = NO_MOVE;
- draw_joystick();
- }
- window_set(Joystick, WIN_CURSOR, cursor, 0);
- window_set(Draw, WIN_CURSOR, cursor, 0);
- }
-